#ifndef DAEMONINSTANCE_H_INCLUDED
#define DAEMONINSTANCE_H_INCLUDED

#include <Ape/Object.h>
#include <Ape/ShPtr.h>
#include <Ape/CLI/ArgumentsParser.h>
#include <Ape/MT/MailBox.h>
#include <Ape/MT/Letter.h>
#include <Ape/Collections/Array.h>
#include <Ape/Collections/LinkedList.h>
#include <Ape/Collections/Map.h>
#include <Ape/Ext/SharedLibrary.h>

#include <MultiplexD/WorkerModel/MultiplexLetter.h>
#include <MultiplexD/DaemonOptions.h>
#include <MultiplexD/Logging/Logger.h>

// API message data
#include <MultiplexD/DaemonAPI/ShutdownRequest.h>
#include <MultiplexD/DaemonAPI/AddWorkerRequest.h>

namespace MultiplexD {
	namespace WorkerModel {
		class MultiplexWorker;
	}
	
	class DaemonInstance : public Ape::Object {
		TYPE_NAME("MultiplexD::DaemonInstance")
	private:
		DaemonInstance();
		DaemonOptions m_Options;
		Ape::ShPtr<Ape::CLI::ArgumentsParser> m_ArgsParser;
		Ape::MT::MailBox<MultiplexD::WorkerModel::MultiplexLetter> m_MailBox;
		
		Ape::Collections::Map<Ape::String, Ape::Ext::SharedLibrary*> m_ShLibs;
		Ape::Collections::Map<Ape::String, WorkerModel::MultiplexWorker*> m_Workers;
		Ape::Collections::LinkedList<Ape::String> m_WorkerNames;
		Logging::Logger m_Logger;
	public:
		virtual ~DaemonInstance();
		
		const DaemonOptions& Options() const;
		DaemonOptions& OptionsVolatile();
		
		void ReadConfiguration(const Ape::Collections::Array<Ape::String>& args);
		void StartUp();
		
		Ape::MT::MailBox<MultiplexD::WorkerModel::MultiplexLetter>& MailBox();
		
		static DaemonInstance* Get();
		Logging::Logger& Logger();
		
		void HandleError(Ape::Exception& exc);
		
		void AddDefaultWorkers();
		void ShutdownAllWorkers();
		// Mail handlers
		void HandleShutdownRequest(const WorkerModel::MultiplexLetter& letter, DaemonAPI::ShutdownData* data);
		void HandleAddWorkerRequest(const WorkerModel::MultiplexLetter& letter, DaemonAPI::AddWorkerData* data);
	};
}

#endif // DAEMONINSTANCE_H_INCLUDED

